package com.huanzhidadi.springsecurity.service.impl;

import com.huanzhidadi.springsecurity.model.BaseResultVO;
import com.huanzhidadi.springsecurity.model.LoginUser;
import com.huanzhidadi.springsecurity.model.User;
import com.huanzhidadi.springsecurity.service.LoginService;
import com.huanzhidadi.springsecurity.util.RedisUtil;
import com.huanzhidadi.springsecurity.util.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationProvider authenticationProvider;

    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public BaseResultVO login(LoginUser loginUser) {

        // AuthenticationManager authenticate进行用户认证
        UsernamePasswordAuthenticationToken authenticationToken
                = new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword());
        Authentication authenticate = authenticationProvider.authenticate(authenticationToken);

        // 如果认证没通过，给出对应提示
        if (Objects.isNull(authenticate)) {
            log.error("访问拒绝：用户名或密码错误！");
            throw new BadCredentialsException("访问拒绝：用户名或密码错误！");
        }

        // 如果认证通过，使用userid生成一个jwt，jwt存入BaseResultVO返回
        LoginUser principal = (LoginUser) authenticate.getPrincipal();
        User user = principal.getUser();
        String token = tokenUtil.generateLoginToken(String.valueOf(user.getId()), null);
        Map<String, String> map = new HashMap<>();
        map.put("token", token);
        // 把完整的用户信息存入redis userid作为key
        redisUtil.setExObjectValue("security:" + user.getId(), principal, 300, TimeUnit.SECONDS);
        return BaseResultVO.success(map);
    }

    @Override
    public BaseResultVO logout() {
        // 获取SecurityContextHolder中的用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 删除redis中的值
        redisUtil.removeCache("security:" + loginUser.getUser().getId());
        // 清空SecurityContextHolder
        SecurityContextHolder.clearContext();
        return BaseResultVO.success("退出成功");
    }
}
